//
// Copyright 2019 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

protocol Output {
    associatedtype T

    func write(_ data: T)
}

extension Output {
    func any() -> AnyOutput<T> {
        return AnyOutput(self)
    }
}

protocol OutputBuffer: Output {
    func flush() -> T
}

protocol StringOutput: Output where T == String {}

class AnyOutput<S>: Output {
    typealias T = S

    private let write: (S) -> Void

    init<U: Output>(_ output: U) where U.T == S {
        write = output.write
    }

    func write(_ data: S) {
        write(data)
    }
}

class StringOutputBuffer: StringOutput {
    private var buffer: String = ""

    func flush() -> String {
        defer {
            buffer = ""
        }
        return buffer
    }

    func write(_ data: String) {
        buffer += data
    }
}
